"""
交易报告生成器

生成交易相关的报告，包括订单统计、交易汇总、盈亏分析等。
"""

from typing import Dict, List, Optional, Any, Tuple
from datetime import datetime, timedelta
from dataclasses import dataclass, field
from decimal import Decimal
from collections import defaultdict

from .report_generator import ReportGenerator, ReportData, ReportConfig
from ..trading.order_manager import Order, OrderStatus, OrderType
from ..trading.execution_engine import ExecutionSlice, ExecutionResult


@dataclass
class OrderSummary:
    """订单汇总"""
    total_orders: int = 0
    filled_orders: int = 0
    cancelled_orders: int = 0
    rejected_orders: int = 0
    pending_orders: int = 0
    
    total_volume: Decimal = Decimal('0')
    filled_volume: Decimal = Decimal('0')
    
    avg_fill_price: Decimal = Decimal('0')
    fill_rate: float = 0.0
    
    # 按类型统计
    market_orders: int = 0
    limit_orders: int = 0
    stop_orders: int = 0
    
    # 按方向统计
    buy_orders: int = 0
    sell_orders: int = 0
    
    buy_volume: Decimal = Decimal('0')
    sell_volume: Decimal = Decimal('0')


@dataclass
class TradingSummary:
    """交易汇总"""
    total_trades: int = 0
    profitable_trades: int = 0
    losing_trades: int = 0
    
    total_pnl: Decimal = Decimal('0')
    realized_pnl: Decimal = Decimal('0')
    unrealized_pnl: Decimal = Decimal('0')
    
    gross_profit: Decimal = Decimal('0')
    gross_loss: Decimal = Decimal('0')
    
    win_rate: float = 0.0
    profit_factor: float = 0.0
    avg_profit: Decimal = Decimal('0')
    avg_loss: Decimal = Decimal('0')
    
    max_profit: Decimal = Decimal('0')
    max_loss: Decimal = Decimal('0')
    
    total_commission: Decimal = Decimal('0')
    total_slippage: Decimal = Decimal('0')


@dataclass
class TradingReportData:
    """交易报告数据"""
    orders: List[Order] = field(default_factory=list)
    executions: List[ExecutionSlice] = field(default_factory=list)
    
    start_date: Optional[datetime] = None
    end_date: Optional[datetime] = None
    
    # 统计数据
    order_summary: Optional[OrderSummary] = None
    trading_summary: Optional[TradingSummary] = None
    
    # 按时间统计
    daily_stats: Dict[str, Dict[str, Any]] = field(default_factory=dict)
    
    # 按品种统计
    symbol_stats: Dict[str, Dict[str, Any]] = field(default_factory=dict)
    
    # 按策略统计
    strategy_stats: Dict[str, Dict[str, Any]] = field(default_factory=dict)


class TradingReportGenerator(ReportGenerator):
    """
    交易报告生成器
    
    生成详细的交易报告，包括订单统计、执行分析、盈亏汇总等。
    """
    
    def __init__(self, config: ReportConfig):
        """初始化交易报告生成器"""
        super().__init__(config)
    
    def collect_data(self, **kwargs) -> ReportData:
        """收集交易报告数据"""
        orders = kwargs.get('orders', [])
        executions = kwargs.get('executions', [])
        
        # 过滤时间范围
        if self.config.start_date or self.config.end_date:
            filtered_orders = []
            filtered_executions = []
            
            for order in orders:
                if self.config.start_date and order.created_time < self.config.start_date:
                    continue
                if self.config.end_date and order.created_time > self.config.end_date:
                    continue
                filtered_orders.append(order)
            
            for execution in executions:
                if self.config.start_date and execution.timestamp < self.config.start_date:
                    continue
                if self.config.end_date and execution.timestamp > self.config.end_date:
                    continue
                filtered_executions.append(execution)
            
            orders = filtered_orders
            executions = filtered_executions
        
        # 创建交易报告数据
        trading_data = TradingReportData(
            orders=orders,
            executions=executions,
            start_date=self.config.start_date,
            end_date=self.config.end_date
        )
        
        # 计算统计数据
        trading_data.order_summary = self._calculate_order_summary(orders)
        trading_data.trading_summary = self._calculate_trading_summary(executions)
        trading_data.daily_stats = self._calculate_daily_stats(orders, executions)
        trading_data.symbol_stats = self._calculate_symbol_stats(orders, executions)
        trading_data.strategy_stats = self._calculate_strategy_stats(orders, executions)
        
        # 创建报告数据
        report_data = ReportData(
            title=self.config.title or "交易报告",
            subtitle=f"交易期间: {self.format_datetime(self.config.start_date or datetime.min, 'date')} - {self.format_datetime(self.config.end_date or datetime.now(), 'date')}"
        )
        
        # 添加摘要
        if trading_data.order_summary and trading_data.trading_summary:
            report_data.summary = {
                "总订单数": trading_data.order_summary.total_orders,
                "成交订单数": trading_data.order_summary.filled_orders,
                "成交率": f"{trading_data.order_summary.fill_rate:.2%}",
                "总交易数": trading_data.trading_summary.total_trades,
                "胜率": f"{trading_data.trading_summary.win_rate:.2%}",
                "总盈亏": self.format_number(float(trading_data.trading_summary.total_pnl), "currency"),
                "盈利因子": f"{trading_data.trading_summary.profit_factor:.2f}"
            }
        
        # 添加详细表格
        if self.config.include_tables:
            # 订单统计表
            if trading_data.order_summary:
                order_table = self._create_order_summary_table(trading_data.order_summary)
                report_data.tables.append(order_table)
            
            # 交易统计表
            if trading_data.trading_summary:
                trading_table = self._create_trading_summary_table(trading_data.trading_summary)
                report_data.tables.append(trading_table)
            
            # 每日统计表
            if trading_data.daily_stats:
                daily_table = self._create_daily_stats_table(trading_data.daily_stats)
                report_data.tables.append(daily_table)
            
            # 品种统计表
            if trading_data.symbol_stats:
                symbol_table = self._create_symbol_stats_table(trading_data.symbol_stats)
                report_data.tables.append(symbol_table)
        
        # 添加章节
        if self.config.include_details:
            # 订单详情
            if orders:
                order_details = self._create_order_details_section(orders[:50])  # 限制显示数量
                report_data.sections.append(order_details)
            
            # 执行详情
            if executions:
                execution_details = self._create_execution_details_section(executions[:50])
                report_data.sections.append(execution_details)
        
        # 添加元数据
        report_data.metadata = {
            "report_type": "trading",
            "data_range": {
                "start_date": self.config.start_date.isoformat() if self.config.start_date else None,
                "end_date": self.config.end_date.isoformat() if self.config.end_date else None
            },
            "statistics": {
                "total_orders": len(orders),
                "total_executions": len(executions)
            }
        }
        
        return report_data
    
    def _calculate_order_summary(self, orders: List[Order]) -> OrderSummary:
        """计算订单汇总统计"""
        if not orders:
            return OrderSummary()
        
        summary = OrderSummary()
        summary.total_orders = len(orders)
        
        filled_volume = Decimal('0')
        total_fill_value = Decimal('0')
        
        for order in orders:
            # 按状态统计
            if order.status == OrderStatus.FILLED:
                summary.filled_orders += 1
                filled_volume += order.filled_quantity
                if order.avg_fill_price and order.filled_quantity:
                    total_fill_value += order.avg_fill_price * order.filled_quantity
            elif order.status == OrderStatus.CANCELLED:
                summary.cancelled_orders += 1
            elif order.status == OrderStatus.REJECTED:
                summary.rejected_orders += 1
            elif order.status in [OrderStatus.PENDING, OrderStatus.SUBMITTED]:
                summary.pending_orders += 1
            
            # 按类型统计
            if order.order_type == OrderType.MARKET:
                summary.market_orders += 1
            elif order.order_type == OrderType.LIMIT:
                summary.limit_orders += 1
            elif order.order_type in [OrderType.STOP, OrderType.STOP_LIMIT]:
                summary.stop_orders += 1
            
            # 按方向统计
            if order.quantity > 0:
                summary.buy_orders += 1
                summary.buy_volume += abs(order.quantity)
            else:
                summary.sell_orders += 1
                summary.sell_volume += abs(order.quantity)
            
            summary.total_volume += abs(order.quantity)
        
        summary.filled_volume = filled_volume
        summary.fill_rate = summary.filled_orders / summary.total_orders if summary.total_orders > 0 else 0.0
        
        if filled_volume > 0:
            summary.avg_fill_price = total_fill_value / filled_volume
        
        return summary
    
    def _calculate_trading_summary(self, executions: List[ExecutionSlice]) -> TradingSummary:
        """计算交易汇总统计"""
        if not executions:
            return TradingSummary()
        
        summary = TradingSummary()
        summary.total_trades = len(executions)
        
        profits = []
        losses = []
        
        for execution in executions:
            # ExecutionSlice没有pnl, commission, slippage属性，使用计算值
            pnl = Decimal('0')  # 需要从其他地方计算
            commission = Decimal('0')  # 需要从其他地方计算
            slippage = Decimal('0')  # 需要从其他地方计算
            
            # 如果有平均价格和数量，可以计算一些基本值
            if execution.avg_price and execution.filled_quantity > 0:
                # 这里可以添加更复杂的计算逻辑
                pass
            
            summary.total_pnl += pnl
            summary.total_commission += commission
            summary.total_slippage += slippage
            
            if pnl > 0:
                summary.profitable_trades += 1
                summary.gross_profit += pnl
                profits.append(pnl)
                if pnl > summary.max_profit:
                    summary.max_profit = pnl
            elif pnl < 0:
                summary.losing_trades += 1
                summary.gross_loss += abs(pnl)
                losses.append(abs(pnl))
                if abs(pnl) > summary.max_loss:
                    summary.max_loss = abs(pnl)
        
        # 计算比率
        if summary.total_trades > 0:
            summary.win_rate = summary.profitable_trades / summary.total_trades
        
        if summary.gross_loss > 0:
            summary.profit_factor = float(summary.gross_profit / summary.gross_loss)
        
        if profits:
            summary.avg_profit = sum(profits) / Decimal(len(profits))
        
        if losses:
            summary.avg_loss = sum(losses) / Decimal(len(losses))
        
        return summary
    
    def _calculate_daily_stats(
        self,
        orders: List[Order],
        executions: List[ExecutionSlice]
    ) -> Dict[str, Dict[str, Any]]:
        """计算每日统计"""
        daily_stats = defaultdict(lambda: {
            'orders': 0,
            'filled_orders': 0,
            'executions': 0,
            'pnl': Decimal('0'),
            'volume': Decimal('0'),
            'commission': Decimal('0')
        })
        
        # 统计订单
        for order in orders:
            date_key = order.created_at.strftime('%Y-%m-%d')
            daily_stats[date_key]['orders'] += 1
            if order.status == OrderStatus.FILLED:
                daily_stats[date_key]['filled_orders'] += 1
                daily_stats[date_key]['volume'] += abs(order.filled_quantity or Decimal('0'))
        
        # 统计执行
        for execution in executions:
            date_key = (execution.executed_at or execution.created_at).strftime('%Y-%m-%d')
            daily_stats[date_key]['executions'] += 1
            daily_stats[date_key]['pnl'] += Decimal('0')  # 需要计算
            daily_stats[date_key]['commission'] += Decimal('0')  # 需要计算
        
        return dict(daily_stats)
    
    def _calculate_symbol_stats(
        self,
        orders: List[Order],
        executions: List[ExecutionSlice]
    ) -> Dict[str, Dict[str, Any]]:
        """计算品种统计"""
        symbol_stats = defaultdict(lambda: {
            'orders': 0,
            'filled_orders': 0,
            'executions': 0,
            'pnl': Decimal('0'),
            'volume': Decimal('0'),
            'commission': Decimal('0')
        })
        
        # 统计订单
        for order in orders:
            symbol = order.symbol
            symbol_stats[symbol]['orders'] += 1
            if order.status == OrderStatus.FILLED:
                symbol_stats[symbol]['filled_orders'] += 1
                symbol_stats[symbol]['volume'] += abs(order.filled_quantity or Decimal('0'))
        
        # 统计执行
        for execution in executions:
            symbol = execution.symbol
            symbol_stats[symbol]['executions'] += 1
            symbol_stats[symbol]['pnl'] += Decimal('0')  # 需要计算
            symbol_stats[symbol]['commission'] += Decimal('0')  # 需要计算
        
        return dict(symbol_stats)
    
    def _calculate_strategy_stats(
        self,
        orders: List[Order],
        executions: List[ExecutionSlice]
    ) -> Dict[str, Dict[str, Any]]:
        """计算策略统计"""
        strategy_stats = defaultdict(lambda: {
            'orders': 0,
            'filled_orders': 0,
            'executions': 0,
            'pnl': Decimal('0'),
            'volume': Decimal('0'),
            'commission': Decimal('0')
        })
        
        # 统计订单
        for order in orders:
            strategy = getattr(order, 'strategy_id', 'Unknown')
            strategy_stats[strategy]['orders'] += 1
            if order.status == OrderStatus.FILLED:
                strategy_stats[strategy]['filled_orders'] += 1
                strategy_stats[strategy]['volume'] += abs(order.filled_quantity or Decimal('0'))
        
        # 统计执行
        for execution in executions:
            strategy = getattr(execution, 'strategy_id', 'Unknown')
            strategy_stats[strategy]['executions'] += 1
            strategy_stats[strategy]['pnl'] += Decimal('0')  # 需要计算
            strategy_stats[strategy]['commission'] += Decimal('0')  # 需要计算
        
        return dict(strategy_stats)
    
    def _create_order_summary_table(self, summary: OrderSummary) -> Dict[str, Any]:
        """创建订单汇总表格"""
        headers = ["指标", "数值"]
        rows = [
            ["总订单数", summary.total_orders],
            ["成交订单数", summary.filled_orders],
            ["取消订单数", summary.cancelled_orders],
            ["拒绝订单数", summary.rejected_orders],
            ["待处理订单数", summary.pending_orders],
            ["成交率", f"{summary.fill_rate:.2%}"],
            ["总交易量", self.format_number(float(summary.total_volume))],
            ["成交量", self.format_number(float(summary.filled_volume))],
            ["平均成交价", self.format_number(float(summary.avg_fill_price), "currency")],
            ["市价单数", summary.market_orders],
            ["限价单数", summary.limit_orders],
            ["止损单数", summary.stop_orders],
            ["买单数", summary.buy_orders],
            ["卖单数", summary.sell_orders],
            ["买入量", self.format_number(float(summary.buy_volume))],
            ["卖出量", self.format_number(float(summary.sell_volume))]
        ]
        
        return self.create_table("订单统计汇总", headers, rows)
    
    def _create_trading_summary_table(self, summary: TradingSummary) -> Dict[str, Any]:
        """创建交易汇总表格"""
        headers = ["指标", "数值"]
        rows = [
            ["总交易数", summary.total_trades],
            ["盈利交易数", summary.profitable_trades],
            ["亏损交易数", summary.losing_trades],
            ["胜率", f"{summary.win_rate:.2%}"],
            ["总盈亏", self.format_number(float(summary.total_pnl), "currency")],
            ["总盈利", self.format_number(float(summary.gross_profit), "currency")],
            ["总亏损", self.format_number(float(summary.gross_loss), "currency")],
            ["盈利因子", f"{summary.profit_factor:.2f}"],
            ["平均盈利", self.format_number(float(summary.avg_profit), "currency")],
            ["平均亏损", self.format_number(float(summary.avg_loss), "currency")],
            ["最大盈利", self.format_number(float(summary.max_profit), "currency")],
            ["最大亏损", self.format_number(float(summary.max_loss), "currency")],
            ["总手续费", self.format_number(float(summary.total_commission), "currency")],
            ["总滑点", self.format_number(float(summary.total_slippage), "currency")]
        ]
        
        return self.create_table("交易统计汇总", headers, rows)
    
    def _create_daily_stats_table(self, daily_stats: Dict[str, Dict[str, Any]]) -> Dict[str, Any]:
        """创建每日统计表格"""
        headers = ["日期", "订单数", "成交数", "执行数", "盈亏", "交易量", "手续费"]
        rows = []
        
        for date in sorted(daily_stats.keys()):
            stats = daily_stats[date]
            rows.append([
                date,
                stats['orders'],
                stats['filled_orders'],
                stats['executions'],
                self.format_number(float(stats['pnl']), "currency"),
                self.format_number(float(stats['volume'])),
                self.format_number(float(stats['commission']), "currency")
            ])
        
        format_rules = {
            "盈亏": "currency",
            "交易量": "default",
            "手续费": "currency"
        }
        
        return self.create_table("每日交易统计", headers, rows, format_rules)
    
    def _create_symbol_stats_table(self, symbol_stats: Dict[str, Dict[str, Any]]) -> Dict[str, Any]:
        """创建品种统计表格"""
        headers = ["品种", "订单数", "成交数", "执行数", "盈亏", "交易量", "手续费"]
        rows = []
        
        # 按盈亏排序
        sorted_symbols = sorted(symbol_stats.items(), key=lambda x: float(x[1]['pnl']), reverse=True)
        
        for symbol, stats in sorted_symbols:
            rows.append([
                symbol,
                stats['orders'],
                stats['filled_orders'],
                stats['executions'],
                self.format_number(float(stats['pnl']), "currency"),
                self.format_number(float(stats['volume'])),
                self.format_number(float(stats['commission']), "currency")
            ])
        
        format_rules = {
            "盈亏": "currency",
            "交易量": "default",
            "手续费": "currency"
        }
        
        return self.create_table("品种交易统计", headers, rows, format_rules)
    
    def _create_order_details_section(self, orders: List[Order]) -> Dict[str, Any]:
        """创建订单详情章节"""
        order_list = []
        for order in orders:
            order_info = {
                "订单ID": order.order_id,
                "品种": order.symbol,
                "类型": order.order_type.value,
                "方向": "买入" if order.quantity > 0 else "卖出",
                "数量": abs(order.quantity),
                "价格": float(order.price) if order.price else "市价",
                "状态": order.status.value,
                "创建时间": self.format_datetime(order.created_at)
            }
            order_list.append(order_info)
        
        return self.create_section("订单详情", order_list, "list")
    
    def _create_execution_details_section(self, executions: List[ExecutionSlice]) -> Dict[str, Any]:
        """创建执行详情章节"""
        execution_list = []
        for execution in executions:
            execution_info = {
                "执行ID": execution.slice_id,
                "订单ID": execution.parent_order_id,
                "品种": execution.symbol,
                "数量": float(execution.quantity),
                "价格": float(execution.avg_price or Decimal('0')),
                "盈亏": float(Decimal('0')),  # 需要计算
                "手续费": float(Decimal('0')),  # 需要计算
                "执行时间": self.format_datetime(execution.executed_at or execution.created_at)
            }
            execution_list.append(execution_info)
        
        return self.create_section("执行详情", execution_list, "list")
    
    def generate_content(self, data: ReportData) -> str:
        """生成报告内容"""
        return self.generate_to_text(data)